package com.gzxw.mogublog.admin.annotation.OperationLogger;

import com.alibaba.fastjson.JSONObject;
import com.gzxw.mogublog.base.holder.RequestHolder;
import com.gzxw.mogublog.commons.config.security.LoginUser;
import com.gzxw.mogublog.utils.AopUtils;
import com.gzxw.mogublog.utils.AspectUtil;
import com.gzxw.mogublog.utils.IpUtils;
import com.gzxw.mogublog.xo.service.SysLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.RequestUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

@Component
@Aspect
@Slf4j
public class OperationLogAspect {

    private Date startTime;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    // 设置操作日志切入点，在注解的位置切入代码
    @Pointcut("@annotation(operationLogger))")
    public void operLogPointCut(OperationLogger operationLogger) {
    }

    @Around(value = "operLogPointCut(operationLogger)")
    public Object doAround(ProceedingJoinPoint joinPoint, OperationLogger operationLogger) throws Throwable {

        startTime = new Date();
        Object result = joinPoint.proceed();
        try {
            // 日志收集
            handle(joinPoint);
        } catch (Exception e) {
            log.error("日志记录出错了!", e);

        }
        return result;
    }

    // 管理员日志收集
    private void handle(ProceedingJoinPoint joinPoint) throws Exception {

        HttpServletRequest request = RequestHolder.getRequest();

        Method currentMethod = AspectUtil.INSTANCE.getMethod(joinPoint);

        OperationLogger annotation = currentMethod.getAnnotation(OperationLogger.class);

        boolean save = annotation.save();

        String bussinessName = AspectUtil.INSTANCE.parseParams(joinPoint.getArgs(), annotation.value());

        if (!save) {
            return;
        }
        Map<String, Object> nameAndArgsMap = AopUtils.getFieldsName(joinPoint);
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String paramJson = JSONObject.toJSONString(nameAndArgsMap);
        String type = request.getMethod();
        String ip = IpUtils.getIpAddr(request);
        String url = request.getRequestURI();

        threadPoolTaskExecutor.execute(new SysLogHandle(paramJson, joinPoint.getTarget().getClass().getName(),
                joinPoint.getSignature().getName(),
                startTime, annotation.value(),
                ip, type, url, loginUser));
    }

}
